define('ace/mode/coffee_highlight_rules', ['require', 'exports', 'module', 'ace/lib/oop', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
  'use strict'

  var oop = require('../lib/oop')
  var TextHighlightRules = require('./text_highlight_rules').TextHighlightRules

  oop.inherits(CoffeeHighlightRules, TextHighlightRules)

  function CoffeeHighlightRules() {
    var identifier = '[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*'

    var keywords = (
      'this|throw|then|try|typeof|super|switch|return|break|by|continue|' +
            'catch|class|in|instanceof|is|isnt|if|else|extends|for|own|' +
            'finally|function|while|when|new|no|not|delete|debugger|do|loop|of|off|' +
            'or|on|unless|until|and|yes|yield|export|import|default'
    )

    var langConstant = (
      'true|false|null|undefined|NaN|Infinity'
    )

    var illegal = (
      'case|const|function|var|void|with|enum|implements|' +
            'interface|let|package|private|protected|public|static'
    )

    var supportClass = (
      'Array|Boolean|Date|Function|Number|Object|RegExp|ReferenceError|String|' +
            'Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|' +
            'SyntaxError|TypeError|URIError|' +
            'ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|' +
            'Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray'
    )

    var supportFunction = (
      'Math|JSON|isNaN|isFinite|parseInt|parseFloat|encodeURI|' +
            'encodeURIComponent|decodeURI|decodeURIComponent|String|'
    )

    var variableLanguage = (
      'window|arguments|prototype|document'
    )

    var keywordMapper = this.createKeywordMapper({
      'keyword': keywords,
      'constant.language': langConstant,
      'invalid.illegal': illegal,
      'language.support.class': supportClass,
      'language.support.function': supportFunction,
      'variable.language': variableLanguage
    }, 'identifier')

    var functionRule = {
      token: ['paren.lparen', 'variable.parameter', 'paren.rparen', 'text', 'storage.type'],
      regex: /(?:(\()((?:"[^")]*?"|'[^')]*?'|\/[^\/)]*?\/|[^()"'\/])*?)(\))(\s*))?([\-=]>)/.source
    }

    var stringEscape = /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)/

    this.$rules = {
      start: [
        {
          token: 'constant.numeric',
          regex: '(?:0x[\\da-fA-F]+|(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:[eE][+-]?\\d+)?)'
        }, {
          stateName: 'qdoc',
          token: 'string', regex: "'''", next: [
            { token: 'string', regex: "'''", next: 'start' },
            { token: 'constant.language.escape', regex: stringEscape },
            { defaultToken: 'string' }
          ]
        }, {
          stateName: 'qqdoc',
          token: 'string',
          regex: '"""',
          next: [
            { token: 'string', regex: '"""', next: 'start' },
            { token: 'paren.string', regex: '#{', push: 'start' },
            { token: 'constant.language.escape', regex: stringEscape },
            { defaultToken: 'string' }
          ]
        }, {
          stateName: 'qstring',
          token: 'string', regex: "'", next: [
            { token: 'string', regex: "'", next: 'start' },
            { token: 'constant.language.escape', regex: stringEscape },
            { defaultToken: 'string' }
          ]
        }, {
          stateName: 'qqstring',
          token: 'string.start', regex: '"', next: [
            { token: 'string.end', regex: '"', next: 'start' },
            { token: 'paren.string', regex: '#{', push: 'start' },
            { token: 'constant.language.escape', regex: stringEscape },
            { defaultToken: 'string' }
          ]
        }, {
          stateName: 'js',
          token: 'string', regex: '`', next: [
            { token: 'string', regex: '`', next: 'start' },
            { token: 'constant.language.escape', regex: stringEscape },
            { defaultToken: 'string' }
          ]
        }, {
          regex: '[{}]', onMatch: function(val, state, stack) {
            this.next = ''
            if (val == '{' && stack.length) {
              stack.unshift('start', state)
              return 'paren'
            }
            if (val == '}' && stack.length) {
              stack.shift()
              this.next = stack.shift() || ''
              if (this.next.indexOf('string') != -1) { return 'paren.string' }
            }
            return 'paren'
          }
        }, {
          token: 'string.regex',
          regex: '///',
          next: 'heregex'
        }, {
          token: 'string.regex',
          regex: /(?:\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)(?:[imgy]{0,4})(?!\w)/
        }, {
          token: 'comment',
          regex: '###(?!#)',
          next: 'comment'
        }, {
          token: 'comment',
          regex: '#.*'
        }, {
          token: ['punctuation.operator', 'text', 'identifier'],
          regex: '(\\.)(\\s*)(' + illegal + ')'
        }, {
          token: 'punctuation.operator',
          regex: '\\.{1,3}'
        }, {
          token: ['keyword', 'text', 'language.support.class',
            'text', 'keyword', 'text', 'language.support.class'],
          regex: '(class)(\\s+)(' + identifier + ')(?:(\\s+)(extends)(\\s+)(' + identifier + '))?'
        }, {
          token: ['entity.name.function', 'text', 'keyword.operator', 'text'].concat(functionRule.token),
          regex: '(' + identifier + ')(\\s*)([=:])(\\s*)' + functionRule.regex
        },
        functionRule,
        {
          token: 'variable',
          regex: '@(?:' + identifier + ')?'
        }, {
          token: keywordMapper,
          regex: identifier
        }, {
          token: 'punctuation.operator',
          regex: '\\,|\\.'
        }, {
          token: 'storage.type',
          regex: '[\\-=]>'
        }, {
          token: 'keyword.operator',
          regex: '(?:[-+*/%<>&|^!?=]=|>>>=?|\\-\\-|\\+\\+|::|&&=|\\|\\|=|<<=|>>=|\\?\\.|\\.{2,3}|[!*+-=><])'
        }, {
          token: 'paren.lparen',
          regex: '[({[]'
        }, {
          token: 'paren.rparen',
          regex: '[\\]})]'
        }, {
          token: 'text',
          regex: '\\s+'
        }],

      heregex: [{
        token: 'string.regex',
        regex: '.*?///[imgy]{0,4}',
        next: 'start'
      }, {
        token: 'comment.regex',
        regex: '\\s+(?:#.*)?'
      }, {
        token: 'string.regex',
        regex: '\\S+'
      }],

      comment: [{
        token: 'comment',
        regex: '###',
        next: 'start'
      }, {
        defaultToken: 'comment'
      }]
    }
    this.normalizeRules()
  }

  exports.CoffeeHighlightRules = CoffeeHighlightRules
})

define('ace/mode/matching_brace_outdent', ['require', 'exports', 'module', 'ace/range'], function(require, exports, module) {
  'use strict'

  var Range = require('../range').Range

  var MatchingBraceOutdent = function() {};

  (function() {
    this.checkOutdent = function(line, input) {
      if (!/^\s+$/.test(line)) { return false }

      return /^\s*\}/.test(input)
    }

    this.autoOutdent = function(doc, row) {
      var line = doc.getLine(row)
      var match = line.match(/^(\s*\})/)

      if (!match) return 0

      var column = match[1].length
      var openBracePos = doc.findMatchingBracket({ row: row, column: column })

      if (!openBracePos || openBracePos.row == row) return 0

      var indent = this.$getIndent(doc.getLine(openBracePos.row))
      doc.replace(new Range(row, 0, row, column - 1), indent)
    }

    this.$getIndent = function(line) {
      return line.match(/^\s*/)[0]
    }
  }).call(MatchingBraceOutdent.prototype)

  exports.MatchingBraceOutdent = MatchingBraceOutdent
})

define('ace/mode/folding/coffee', ['require', 'exports', 'module', 'ace/lib/oop', 'ace/mode/folding/fold_mode', 'ace/range'], function(require, exports, module) {
  'use strict'

  var oop = require('../../lib/oop')
  var BaseFoldMode = require('./fold_mode').FoldMode
  var Range = require('../../range').Range

  var FoldMode = exports.FoldMode = function() {}
  oop.inherits(FoldMode, BaseFoldMode);

  (function() {
    this.getFoldWidgetRange = function(session, foldStyle, row) {
      var range = this.indentationBlock(session, row)
      if (range) { return range }

      var re = /\S/
      var line = session.getLine(row)
      var startLevel = line.search(re)
      if (startLevel == -1 || line[startLevel] != '#') { return }

      var startColumn = line.length
      var maxRow = session.getLength()
      var startRow = row
      var endRow = row

      while (++row < maxRow) {
        line = session.getLine(row)
        var level = line.search(re)

        if (level == -1) { continue }

        if (line[level] != '#') { break }

        endRow = row
      }

      if (endRow > startRow) {
        var endColumn = session.getLine(endRow).length
        return new Range(startRow, startColumn, endRow, endColumn)
      }
    }
    this.getFoldWidget = function(session, foldStyle, row) {
      var line = session.getLine(row)
      var indent = line.search(/\S/)
      var next = session.getLine(row + 1)
      var prev = session.getLine(row - 1)
      var prevIndent = prev.search(/\S/)
      var nextIndent = next.search(/\S/)

      if (indent == -1) {
        session.foldWidgets[row - 1] = prevIndent != -1 && prevIndent < nextIndent ? 'start' : ''
        return ''
      }
      if (prevIndent == -1) {
        if (indent == nextIndent && line[indent] == '#' && next[indent] == '#') {
          session.foldWidgets[row - 1] = ''
          session.foldWidgets[row + 1] = ''
          return 'start'
        }
      } else if (prevIndent == indent && line[indent] == '#' && prev[indent] == '#') {
        if (session.getLine(row - 2).search(/\S/) == -1) {
          session.foldWidgets[row - 1] = 'start'
          session.foldWidgets[row + 1] = ''
          return ''
        }
      }

      if (prevIndent != -1 && prevIndent < indent) { session.foldWidgets[row - 1] = 'start' } else { session.foldWidgets[row - 1] = '' }

      if (indent < nextIndent) { return 'start' } else { return '' }
    }
  }).call(FoldMode.prototype)
})

define('ace/mode/coffee', ['require', 'exports', 'module', 'ace/mode/coffee_highlight_rules', 'ace/mode/matching_brace_outdent', 'ace/mode/folding/coffee', 'ace/range', 'ace/mode/text', 'ace/worker/worker_client', 'ace/lib/oop'], function(require, exports, module) {
  'use strict'

  var Rules = require('./coffee_highlight_rules').CoffeeHighlightRules
  var Outdent = require('./matching_brace_outdent').MatchingBraceOutdent
  var FoldMode = require('./folding/coffee').FoldMode
  var Range = require('../range').Range
  var TextMode = require('./text').Mode
  var WorkerClient = require('../worker/worker_client').WorkerClient
  var oop = require('../lib/oop')

  function Mode() {
    this.HighlightRules = Rules
    this.$outdent = new Outdent()
    this.foldingRules = new FoldMode()
  }

  oop.inherits(Mode, TextMode);

  (function() {
    var indenter = /(?:[({[=:]|[-=]>|\b(?:else|try|(?:swi|ca)tch(?:\s+[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)?|finally))\s*$|^\s*(else\b\s*)?(?:if|for|while|loop)\b(?!.*\bthen\b)/

    this.lineCommentStart = '#'
    this.blockComment = { start: '###', end: '###' }

    this.getNextLineIndent = function(state, line, tab) {
      var indent = this.$getIndent(line)
      var tokens = this.getTokenizer().getLineTokens(line, state).tokens

      if (!(tokens.length && tokens[tokens.length - 1].type === 'comment') &&
            state === 'start' && indenter.test(line)) { indent += tab }
      return indent
    }

    this.checkOutdent = function(state, line, input) {
      return this.$outdent.checkOutdent(line, input)
    }

    this.autoOutdent = function(state, doc, row) {
      this.$outdent.autoOutdent(doc, row)
    }

    this.createWorker = function(session) {
      var worker = new WorkerClient(['ace'], 'ace/mode/coffee_worker', 'Worker')
      worker.attachToDocument(session.getDocument())

      worker.on('annotate', function(e) {
        session.setAnnotations(e.data)
      })

      worker.on('terminate', function() {
        session.clearAnnotations()
      })

      return worker
    }

    this.$id = 'ace/mode/coffee'
  }).call(Mode.prototype)

  exports.Mode = Mode
});
(function() {
  window.require(['ace/mode/coffee'], function(m) {
    if (typeof module === 'object' && typeof exports === 'object' && module) {
      module.exports = m
    }
  })
})()
